package com.lmaos.basetools.menuList;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import com.lmaos.basetools.sText.TextUtils;

public class MenuMgImpl implements MenuMg{
	private AtomicLong indexIds = new AtomicLong(0);
	private Map<Long,MenuItem> existIds = new ConcurrentHashMap<Long,MenuItem>(256);
	private volatile Map<String,MenuDirectory> directorySearch = new ConcurrentHashMap<String,MenuDirectory>(256);
	private volatile Map<String,MenuItem> menuItemSearch = new ConcurrentHashMap<String,MenuItem>(256);
	private MenuDirectory directory = new MenuDirectory("/",directorySearch,menuItemSearch); // 根目录
	private ReadWriteLock menuControlLock = new ReentrantReadWriteLock();
	
	@Override
	public void addMenuItem(MenuItem menuItem){
		_addMenuItem(menuItem);
	}
	protected boolean _addMenuItem(MenuItem menuItem) {
		long menuid = menuItem.getMenuid();
		// 如果id为空则动态设置一个id
		if(menuid <= 0){
			menuItem.setMenuid(getIndexId());
		}else if(existIds.containsKey(menuid)){
			return false;
		}
		directory.addMenuItem(menuItem);
		menuItemSearch.put(menuItem.getAbsoluteMenuPath(), menuItem);
		existIds.put(menuItem.getMenuid(), menuItem);	// 设置id对应的值
		return true;
	}
	@Override
	public void addMenuItems(MenuItem... menuItems) {
		menuControlLock.writeLock().lock();
		for (MenuItem menuItem : menuItems) {
			try {
				_addMenuItem(menuItem);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		menuControlLock.writeLock().unlock();
	}

	@Override
	public long getIndexId() {
		long indexId = 0;
		while(existIds.containsKey(indexId = indexIds.incrementAndGet()));
		return indexId;
	}

	@Override
	public List<MenuItem> findMenuItemByURLPath(String startPath) {
		List<MenuItem> menuItems = new ArrayList<MenuItem>();
		
		menuControlLock.readLock().lock();	// 读锁
		for(MenuItem menuItem : menuItemSearch.values()){
			if(menuItem.getAbsoluteMenuPath().startsWith(startPath)){
				menuItems.add(menuItem);	// 释放读锁
			}
		}
		menuControlLock.readLock().unlock();
		return menuItems;
	}

	@Override
	public MenuItem getMenuItemByURL(String url) {
		MenuItem menuItem = null;
		try {
			menuControlLock.readLock().lock();
			menuItem = menuItemSearch.get(url);
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			menuControlLock.readLock().unlock();
		}
		return menuItem;
	}

	@Override
	public MenuDirectory getMenuDirectoryByPath(String path) {
		path = TextUtils.formatTextEnd(path.replace("\\", "/"), "/");
		return directorySearch.get(path);
	}
	@Override
	public void remove(String url) {
		menuControlLock.writeLock().lock(); // 设置写锁
		_remove(url);
		menuControlLock.writeLock().unlock(); // 释放写锁
	}
	// 非同步
	protected void _remove(String url) {
		if(TextUtils.isEmpty(url)||!url.startsWith("/")){
			return;
		}
		try {
			if(url.endsWith("/")){ // 是一个目录
				MenuDirectory directory = getMenuDirectoryByPath(url);
				if(directory!=null){
					directory.clearDir();
					Set<String> menuItemPaths = new HashSet<String>(menuItemSearch.keySet());
					for (String keys : menuItemPaths) {
						if(keys.startsWith(url)&&!keys.equals("/")){
							menuItemSearch.remove(keys);
						}
					}
					Set<String> directoryPaths = new HashSet<String>(directorySearch.keySet());
					for (String keys : directoryPaths) {
						if(keys.startsWith(url)&&!keys.equals("/")){
							directorySearch.remove(keys);
						}
					}
				}
			}else{ // 是一个文件
				int path_endIndex = url.lastIndexOf("/");
				String path = url.substring(0, path_endIndex);
				String menuItemName = url.substring(path_endIndex+1);
				MenuDirectory directory = getMenuDirectoryByPath(path);
				if(directory!=null){
					directory.removeMenuItemName(menuItemName);
					menuItemSearch.remove(url);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	@Override
	public List<MenuItem> getAllMenuItem() {
		menuControlLock.readLock().lock();
		List<MenuItem> menuItems = null;
		try {
			menuItems = new ArrayList<MenuItem>(menuItemSearch.values());
		} catch (Exception e) {
		}
		menuControlLock.readLock().unlock();
		return menuItems;
	}
	@Override
	public MenuDirectory getRootMenuDirectory() {
		return directory;
	}
	@Override
	public MenuItem getMenuItemById(long menuId) {
		return existIds.get(menuId);
	}
	

	@Override
	public int verifyCanCreate(String absoluteMenuPath) {
		if(TextUtils.isBlank(absoluteMenuPath)){
			return verifyCanCreate_BLANK;
		}
		MenuItem menuItem = menuItemSearch.get(absoluteMenuPath);
		if(menuItem!=null&&!menuItem.isTemp()){
			return verifyCanCreate_EXIST;
		}
		
		menuItem = menuItemSearch.get(absoluteMenuPath+"/");
		if(menuItem!=null&&!menuItem.isTemp()){
			return verifyCanCreate_EXIST_DIR;
		}
		
		int endIndex = absoluteMenuPath.length();
		while(endIndex > 0){
			endIndex = absoluteMenuPath.lastIndexOf("/", endIndex-1);
			String path = absoluteMenuPath.substring(0,endIndex);
			if(endIndex!=-1){
				menuItem = menuItemSearch.get(path);
				if(menuItem!=null&&!menuItem.isTemp()){
					return verifyCanCreate_EXIST_FILE;
				}
				menuItem = menuItemSearch.get(path+"/");
				if(menuItem!=null&&!menuItem.isTemp()){
					return verifyCanCreate_EXIST_DIR;
				}
			}
		}
		
		return verifyCanCreate_SUCC;
	}
	@Override
	public void clear(Set<String> urls) {
		menuControlLock.writeLock().lock(); // 设置写锁
		for (String url : urls) {
			_remove(url);
		}
		menuControlLock.writeLock().unlock(); // 释放写锁
		
	}
	public static void main(String[] args) {
		MenuMg mg = new MenuMgImpl();
		mg.addMenuItem(new MenuItem("/a"));
		mg.addMenuItem(new MenuItem("/b/w"));
		mg.addMenuItem(new MenuItem("/b/q"));
		mg.addMenuItem(new MenuItem("/b/e"));
		mg.addMenuItem(new MenuItem("/b/k/f"));
		mg.addMenuItem(new MenuItem("/c/f"));
		mg.remove("/b/");
		System.out.println(mg.getMenuDirectoryByPath("/b"));
		System.out.println(mg.getAllMenuItem());
	}
	
}
